<template>
  <div class="data-lab" :class="{ 'is-embedded': embedded }">
    <header class="lab-header">
      <div>
        <h1>数据实验室</h1>
        <p>从任意接口拉取业务数据，快速分析与可视化，并支持导出 Excel。</p>
      </div>
      <div class="header-actions">
        <div class="header-action-buttons">
          <slot name="header-actions">
            <el-button @click="$emit('navigate-back')" v-if="!embedded">
              返回聊天
            </el-button>
            <el-button type="primary" :loading="loading" @click="handleFetch">
              拉取数据
            </el-button>
          </slot>
        </div>
        <p class="fetch-hint">
          提示：默认示例依赖 dummyjson.com，如在内网无法访问，请改用可访问的接口并确保 json_path 配置正确。
        </p>
      </div>
    </header>

    <section class="lab-body">
      <aside class="lab-sidebar">
        <el-form label-position="top" class="lab-form">
          <el-form-item label="接口地址">
            <el-input v-model="requestForm.url" placeholder="https://api.example.com/data" />
          </el-form-item>
          <div class="form-row">
            <el-form-item label="请求方法">
              <el-select v-model="requestForm.method">
                <el-option label="GET" value="GET" />
                <el-option label="POST" value="POST" />
                <el-option label="PUT" value="PUT" />
                <el-option label="DELETE" value="DELETE" />
              </el-select>
            </el-form-item>
            <el-form-item label="JSON 路径">
              <el-input v-model="requestForm.json_path" placeholder="例如 data.items" />
            </el-form-item>
          </div>
          <div class="form-row">
            <el-form-item label="分组字段">
              <el-input v-model="requestForm.group_by" placeholder="可选，例如 category" />
            </el-form-item>
            <el-form-item label="日期字段">
              <el-input v-model="requestForm.date_field" placeholder="可选，例如 created_at" />
            </el-form-item>
          </div>
          <div class="form-row">
            <el-form-item label="聚合频率">
              <el-select v-model="requestForm.freq" placeholder="可选">
                <el-option label="按天" value="D" />
                <el-option label="按周" value="W" />
                <el-option label="按月" value="M" />
              </el-select>
            </el-form-item>
            <el-form-item label="指标字段">
              <el-input v-model="requestForm.value_field" placeholder="可选，例如 price" />
            </el-form-item>
          </div>
          <el-form-item label="聚合方式">
            <el-select v-model="requestForm.agg">
              <el-option label="计数" value="count" />
              <el-option label="求和" value="sum" />
              <el-option label="平均值" value="mean" />
              <el-option label="最大值" value="max" />
              <el-option label="最小值" value="min" />
            </el-select>
          </el-form-item>
          <el-form-item label="查询参数（JSON，可选）">
            <el-input
              v-model="requestForm.params"
              type="textarea"
              :rows="3"
              placeholder='例如 { "limit": 20 }'
            />
          </el-form-item>
          <el-form-item label="请求头（JSON，可选）">
            <el-input
              v-model="requestForm.headers"
              type="textarea"
              :rows="3"
              placeholder='例如 { "Authorization": "Bearer xxx" }'
            />
          </el-form-item>
        </el-form>

        <section class="preset-section">
          <div class="preset-header">
            <h3>快速示例</h3>
            <span>选择一个示例即可自动填充参数</span>
          </div>
          <div class="preset-list">
            <el-card
              v-for="preset in presets"
              :key="preset.name"
              class="preset-card"
              shadow="hover"
              @click="applyPreset(preset)"
            >
              <h4>{{ preset.name }}</h4>
              <p>{{ preset.description }}</p>
            </el-card>
          </div>
        </section>
      </aside>

      <main class="lab-results">
        <section class="summary-grid" v-if="analysisResult">
          <el-card v-for="item in summaryCards" :key="item.label" class="summary-card" shadow="never">
            <p class="summary-label">{{ item.label }}</p>
            <p class="summary-value">{{ item.value }}</p>
          </el-card>
        </section>

        <el-card class="chart-card" shadow="never">
          <template #header>
            <div class="card-header">
              <span>聚合视图</span>
              <el-tag v-if="chartSummary" size="small">{{ chartSummary }}</el-tag>
            </div>
          </template>
          <div class="chart-placeholder" ref="chartRef">
            <p v-if="!hasChartData">暂无聚合数据，尝试指定分组或日期字段。</p>
          </div>
        </el-card>

        <el-card class="table-card" shadow="never">
          <template #header>
            <div class="card-header">
              <span>原始数据</span>
              <div class="card-actions">
                <el-select
                  v-model="selectedColumns"
                  multiple
                  collapse-tags
                  collapse-tags-tooltip
                  filterable
                  clearable
                  placeholder="选择要导出的列（可搜索）"
                  class="column-select"
                >
                  <el-option
                    v-for="field in availableFields"
                    :key="field"
                    :label="field"
                    :value="field"
                  />
                </el-select>
                <el-tooltip
                  content="导出当前表格显示的数据，不包含上方图表的聚合结果"
                  placement="top"
                >
                  <el-button :loading="exporting" type="success" @click="handleExport">
                    导出 Excel
                  </el-button>
                </el-tooltip>
              </div>
            </div>
          </template>
          <div class="table-header-info">
            当前解析到 {{ tableData.length }} 条记录
          </div>
          <div v-if="!tableData.length" class="table-empty">
            未解析到任何数据，请检查 JSON 路径（json_path）是否正确。
          </div>
          <el-table
            v-else
            :data="tableData"
            height="360"
            stripe
            v-loading="loading"
          >
            <el-table-column
              v-for="field in tableColumns"
              :key="field"
              :prop="field"
              :label="field"
              min-width="160"
              show-overflow-tooltip
            />
          </el-table>
          <p class="export-note">
            仅导出当前表格数据，不包含聚合统计结果。
          </p>
        </el-card>
      </main>
    </section>
  </div>
</template>

<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
import { ElMessage } from 'element-plus'
import * as echarts from 'echarts'
import dataToolsService, { FetchAnalyzeRequest } from '@/services/dataTools'

defineProps<{
  embedded?: boolean
}>()

const emit = defineEmits<{
  (e: 'navigate-back'): void
}>()

const loading = ref(false)
const exporting = ref(false)
const analysisResult = ref<any>(null)
const tableData = ref<any[]>([])
const selectedColumns = ref<string[]>([])
const chartRef = ref<HTMLDivElement | null>(null)
let chartInstance: echarts.ECharts | null = null

const requestForm = reactive({
  url: 'https://dummyjson.com/products',
  method: 'GET',
  json_path: 'products',
  group_by: 'category',
  date_field: '',
  freq: '',
  value_field: 'price',
  agg: 'mean',
  params: '',
  headers: ''
})

const presets = [
  {
    name: '商品分类平均价格',
    description: '统计 Dummy JSON 商品在不同分类的平均价格。',
    request: {
      url: 'https://dummyjson.com/products',
      method: 'GET',
      json_path: 'products',
      group_by: 'category',
      value_field: 'price',
      agg: 'mean'
    }
  },
  {
    name: '用户注册趋势',
    description: '模拟接口：按月统计用户注册数量。',
    request: {
      url: 'https://dummyjson.com/users',
      method: 'GET',
      json_path: 'users',
      date_field: 'birthDate',
      freq: 'M',
      agg: 'count'
    }
  },
  {
    name: '帖子标签计数',
    description: '示例接口：统计不同标签的帖子数量。',
    request: {
      url: 'https://dummyjson.com/posts',
      method: 'GET',
      json_path: 'posts',
      group_by: 'tags',
      agg: 'count'
    }
  }
]

const hasChartData = computed(() => {
  return Boolean(analysisResult.value?.analysis?.aggregation?.data?.length)
})

const chartSummary = computed(() => {
  if (!analysisResult.value?.analysis?.aggregation) {
    return ''
  }
  const agg = analysisResult.value.analysis.aggregation
  const targetField =
    Object.keys(agg.aggregation || {}).find((key) => key !== 'count') ||
    Object.keys(agg.aggregation || {})[0]
  if (!targetField) {
    return ''
  }
  return `指标：${targetField}`
})

const summaryCards = computed(() => {
  if (!analysisResult.value) {
    return []
  }
  const total = analysisResult.value.analysis?.original_count ?? tableData.value.length
  const columns = analysisResult.value.analysis?.columns?.length ?? 0
  const timestamp = analysisResult.value.timestamp
  return [
    { label: '数据条数', value: total },
    { label: '字段数量', value: columns },
    { label: '分析时间', value: new Date(timestamp).toLocaleString() }
  ]
})

const availableFields = computed(() => dataToolsService.extractFields(tableData.value))
const tableColumns = computed(() =>
  selectedColumns.value.length ? selectedColumns.value : availableFields.value.slice(0, 8)
)

const parseJsonField = (value: string) => {
  if (!value.trim()) {
    return undefined
  }
  try {
    return JSON.parse(value)
  } catch (error) {
    throw new Error('JSON 字段解析失败，请检查格式')
  }
}

const buildRequestPayload = (): FetchAnalyzeRequest => {
  const payload: FetchAnalyzeRequest = {
    url: requestForm.url.trim(),
    method: requestForm.method,
    json_path: requestForm.json_path.trim() || undefined,
    group_by: requestForm.group_by.trim() || undefined,
    date_field: requestForm.date_field.trim() || undefined,
    freq: requestForm.freq || undefined,
    value_field: requestForm.value_field.trim() || undefined,
    agg: requestForm.agg || 'count'
  }
  const params = parseJsonField(requestForm.params)
  const headers = parseJsonField(requestForm.headers)
  if (params) payload.params = params
  if (headers) payload.headers = headers
  return payload
}

const renderChart = () => {
  if (!chartRef.value) {
    return
  }
  if (!hasChartData.value) {
    if (chartInstance) {
      chartInstance.dispose()
      chartInstance = null
    }
    return
  }

  const aggregation = analysisResult.value.analysis.aggregation
  const data = aggregation.data || []
  const groupKeys = aggregation.group_by || []
  const labelKey = groupKeys[groupKeys.length - 1]
  const metricKey =
    Object.keys(aggregation.aggregation || {}).find((key) => key !== 'count') ||
    Object.keys(aggregation.aggregation || {})[0] ||
    'count'

  if (!chartInstance) {
    chartInstance = echarts.init(chartRef.value)
  }

  const xAxisData = data.map((row: Record<string, any>) => row[labelKey] ?? '未命名')
  const seriesData = data.map((row: Record<string, any>) => Number(row[metricKey] ?? row.count ?? 0))

  chartInstance.setOption({
    tooltip: { trigger: 'axis' },
    xAxis: { type: 'category', data: xAxisData },
    yAxis: { type: 'value' },
    series: [
      {
        type: 'bar',
        name: metricKey,
        data: seriesData,
        smooth: true,
        areaStyle: {}
      }
    ]
  })
}

const handleFetch = async () => {
  loading.value = true
  try {
    const payload = buildRequestPayload()
    const response = await dataToolsService.fetchAndAnalyze(payload)
    analysisResult.value = response
    tableData.value = Array.isArray(response.full_data) ? response.full_data : []
    selectedColumns.value = []
    ElMessage.success('数据已更新')
    renderChart()
  } catch (error: any) {
    const detail = error?.response?.data?.detail || error?.message || ''
    ElMessage.error(
      detail ||
        '拉取数据失败：请检查接口地址是否可访问（如 dummyjson 在内网可能无法访问）、JSON 路径是否正确，以及字段配置是否匹配。'
    )
    console.error('DataLab fetch error', error)
  } finally {
    loading.value = false
  }
}

const handleExport = async () => {
  if (!tableData.value.length) {
    ElMessage.warning('暂无可导出的数据')
    return
  }
  exporting.value = true
  try {
    const payload = {
      data: tableData.value,
      columns: selectedColumns.value.length ? selectedColumns.value : undefined
    }
    const result = await dataToolsService.exportExcel(payload)
    dataToolsService.downloadExcel(
      result.blob,
      `data_lab_export_${new Date().toISOString().slice(0, 19).replace(/[:T]/g, '-')}.xlsx`
    )
    ElMessage.success('已导出 Excel')
  } catch (error) {
    console.error('DataLab export error', error)
    ElMessage.error('导出失败，请稍后再试')
  } finally {
    exporting.value = false
  }
}

const applyPreset = (preset: (typeof presets)[number]) => {
  Object.assign(requestForm, {
    ...requestForm,
    ...preset.request
  })
  requestForm.params = ''
  requestForm.headers = ''
}

const handleResize = () => {
  chartInstance?.resize()
}

onMounted(() => {
  window.addEventListener('resize', handleResize)
})

onBeforeUnmount(() => {
  window.removeEventListener('resize', handleResize)
  if (chartInstance) {
    chartInstance.dispose()
  }
})
</script>

<style scoped>
.data-lab {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: #f5f7fb;
}

.data-lab.is-embedded {
  height: auto;
  max-height: unset;
}

.lab-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  padding: 24px 32px;
  border-bottom: 1px solid #e5e7eb;
  background: #fff;
}

.lab-header h1 {
  margin: 0;
  font-size: 24px;
}

.lab-header p {
  margin: 8px 0 0;
  color: #6b7280;
}

.header-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}

.header-action-buttons {
  display: flex;
  gap: 12px;
}

.fetch-hint {
  margin: 0;
  font-size: 12px;
  color: #6b7280;
  max-width: 320px;
  text-align: right;
}

.lab-body {
  flex: 1;
  display: flex;
  overflow: hidden;
}

.lab-sidebar {
  width: 360px;
  padding: 24px;
  border-right: 1px solid #e5e7eb;
  overflow-y: auto;
  background: #fff;
}

.lab-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.form-row {
  display: flex;
  gap: 12px;
}

.form-row .el-form-item {
  flex: 1;
}

.preset-section {
  margin-top: 32px;
}

.preset-header h3 {
  margin: 0;
}

.preset-header span {
  color: #6b7280;
  font-size: 12px;
}

.preset-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 12px;
}

.preset-card {
  cursor: pointer;
  border-color: transparent;
}

.preset-card:hover {
  border-color: #409eff;
}

.preset-card h4 {
  margin: 0 0 4px;
}

.preset-card p {
  margin: 0;
  color: #6b7280;
  font-size: 13px;
}

.lab-results {
  flex: 1;
  padding: 24px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.summary-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
}

.summary-card {
  text-align: center;
}

.summary-label {
  margin: 0;
  color: #6b7280;
  font-size: 13px;
}

.summary-value {
  font-size: 20px;
  font-weight: 600;
  margin: 8px 0 0;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.card-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

.column-select {
  width: 280px;
}

.chart-placeholder {
  height: 320px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #9ca3af;
}

.chart-placeholder p {
  margin: 0;
}

.table-header-info {
  margin: 0 0 8px;
  color: #4b5563;
  font-size: 14px;
}

.table-empty {
  padding: 24px;
  text-align: center;
  color: #9ca3af;
  border: 1px dashed #d1d5db;
  border-radius: 8px;
  margin-bottom: 12px;
}

.export-note {
  margin: 12px 0 0;
  font-size: 12px;
  color: #9ca3af;
}

@media (max-width: 1200px) {
  .lab-body {
    flex-direction: column;
  }

  .lab-sidebar {
    width: 100%;
    border-right: none;
    border-bottom: 1px solid #e5e7eb;
  }
}

@media (max-width: 768px) {
  .lab-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
    padding: 16px;
  }

  .header-actions {
    align-items: flex-start;
    width: 100%;
  }

  .header-action-buttons {
    width: 100%;
    justify-content: flex-end;
  }

  .fetch-hint {
    max-width: 100%;
    text-align: left;
  }

  .lab-sidebar {
    padding: 16px;
  }

  .lab-results {
    padding: 16px;
  }

  .form-row {
    flex-direction: column;
    gap: 8px;
  }

  .summary-grid {
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 12px;
  }

  .card-actions {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }

  .column-select {
    width: 100%;
  }
}

@media (max-width: 480px) {
  .lab-header {
    padding: 12px;
  }

  .lab-header h1 {
    font-size: 20px;
  }

  .lab-sidebar {
    padding: 12px;
  }

  .lab-results {
    padding: 12px;
    gap: 16px;
  }

  .summary-grid {
    grid-template-columns: 1fr;
    gap: 8px;
  }

  .summary-value {
    font-size: 18px;
  }

  .chart-placeholder {
    height: 240px;
  }

  .header-action-buttons {
    flex-wrap: wrap;
    gap: 8px;
  }

  .header-action-buttons .el-button {
    flex: 1;
    min-width: 100px;
  }
}
</style>

